use lazy_static::lazy_static;
use regex::Regex;

use crate::core::{
    analysis::buffer::Buffer,
    base::{
        self,
        util,
    },
};
use crate::core::base::key_word;
use crate::core::base::meta;
use crate::core::model::data::Data;

lazy_static! {
    /// 完全匹配: 一个数字
    pub static ref NUM: Regex = Regex::new(r"^\d+$").unwrap();
    /// 完全匹配: 一个小数
    pub static ref DECIMAL: Regex = Regex::new(r"^\d+\.\d+$").unwrap();
    /// 完全匹配: 一个字符串
    pub static ref STRING: Regex = Regex::new(r"^'\w*'$").unwrap();
    /// 完全匹配: 一个布尔值
    pub static ref BOOL: Regex = Regex::new(r"true|false").unwrap();
    /// 完全匹配: 一个不以数字开头的名称
    pub static ref VAR: Regex = Regex::new(r"[A-Za-z_]+\w*").unwrap();
    /// 完全匹配: 一个null表达式 nul![data_type]
    pub static ref NULL: Regex = Regex::new(r"nul!(\w+)\s*").unwrap();
    /// 形式匹配: 一行注释 // [any]
    pub static ref COMMENTS_LINE: Regex = Regex::new(r"\s*//.*").unwrap();
    /// 形式匹配: 一个赋值操作 [statement]=[expression]
    pub static ref ASSIGNMENT: Regex = Regex::new(r"\s*([^=\r\n]+)\s*=\s*([^=\r\n]+)\s*").unwrap();
    /// 声明匹配: 单个方法的调用 [func_name](args)
    pub static ref S_DO_FUNC: Regex = Regex::new(r"([\w.]*\w)\(([\w',\s]*)\)").unwrap();
    /// 声明匹配: 一个新建值操作 let [var_name]
    pub static ref S_LET : Regex = Regex::new(r"\s*let\s+(\w+)\s*").unwrap();
}

/// 匹配器
pub struct MatchMachine {
    buffer: Buffer,
}

impl Default for MatchMachine {
    fn default() -> Self {
        Self { buffer: Buffer::default() }
    }
}

impl MatchMachine {
    pub fn buffer_free(&mut self) -> Vec<String> {
        self.buffer.end()
    }

    pub fn match_line(&mut self, yuzu: &str, line: &str) -> u8 {
        let status = match_line(yuzu, line);
        if status == 2 {
            let buf = self.buffer.end();
            // todo get buffer and to exec
            base::log().debug(format!("get buffer {:?}", buf));
        } else if status == 1 {
            self.buffer.append(line);
        }
        status
    }
}

/// 单行匹配 返回0无事发生 返回1开始buffer 返回2结束buffer
fn match_line(yuzu: &str, line: &str) -> u8 {
    // 解析顺序很重要
    // 1 空白 2 注释 3 赋值
    if line.trim().is_empty() {
        //单行空白
        base::log().debug(format!("[{}] continue with black", yuzu));
    } else if COMMENTS_LINE.is_match(line) {
        // 单行注释
        base::log().debug(format!("[{}] continue with comments", yuzu));
    } else if ASSIGNMENT.is_match(line) {
        // 赋值操作
        for capture in ASSIGNMENT.captures_iter(line) {
            let statement = util::capture_str(&capture, 1);
            let expression = util::capture_str(&capture, 2);
            let data = match_expression(yuzu, &expression);
            match_statement(yuzu, statement.trim(), data);
        }
    } else if S_DO_FUNC.is_match(line) {
        // 单个方法
        for capture in S_DO_FUNC.captures_iter(line) {
            let func_name = util::capture_str(&capture, 1);
            let func_args = util::capture_str(&capture, 2);
            let args = util::args_to_vec(yuzu, &func_args);
            let func = meta::get_func(&func_name);
            let result: Option<Data> = func(args);
            base::log().debug(format!("exec `{}` and get result `{:?}`", func_name, result));
        }
    } else {
        return 1;
    }
    0
}

/// 表达式匹配
fn match_expression(yuzu: &str, expression: &str) -> Data {
    //todo expression to value
    let value = expression;
    util::data_transfer(yuzu, value)
}

/// 声明匹配
fn match_statement(yuzu: &str, statement: &str, data: Data) {
    if S_LET.is_match(statement) {
        for capture in S_LET.captures_iter(statement) {
            let var = util::capture_str(&capture, 1);
            key_word::let_(yuzu, &var, &data);
        }
    } else if VAR.is_match(statement) {
        key_word::un_let(yuzu, statement, &data);
    } else {
        base::log().println(format!("do not supported.md statement `{}`", statement))
    }
}